// [[ OnflowGenerator File UUID: fb1a53c6a77541b0a0ee5ff0de7c5595  ]]
package com.itdct.onflow.system.file.manager

import cn.hutool.core.lang.UUID
import cn.hutool.crypto.SecureUtil
import com.itdct.onflow.core.constant.ReturnCode
import com.itdct.onflow.core.extend.insertEx
import com.itdct.onflow.core.util.TimeUtil
import com.itdct.onflow.system.common.base.BaseManager
import com.itdct.onflow.system.file.constant.SysFileGradeConst
import com.itdct.onflow.system.file.dto.SysFileTransferToLocalDTO
import com.itdct.onflow.system.file.entity.SysFileEntity
import com.itdct.onflow.system.file.manager.upload.BaseFileTransfer
import com.itdct.onflow.system.file.mapper.SysFileMapper
import org.springframework.stereotype.Component
import org.springframework.web.multipart.MultipartFile
import java.io.File
import java.util.*

/**
 * @author DCTANT
 * @date 2025-09-23 16:16:15
 * @version 1.0
 * @description 系统文件管理中间层
 */
@Component
class SysFileManager(
    val sysFileMapper: SysFileMapper,
    val baseFileTransfer: BaseFileTransfer
) : BaseManager() {

    fun uploadFile(
        transferFile: File,
        originalFileName: String,
        moduleName: String,
        fileGrade: Int = SysFileGradeConst.MEDIUM,
        sourceType: Int,
        expireDate: String? = null,
        additionalPath: String? = null,
        deleteAfterUpload: Boolean = false
    ): SysFileEntity {
        val fileConfig = onflowConfig.file

        val md5 = SecureUtil.md5(transferFile)

        var storePath = "$moduleName/"
        if (fileConfig.datePath) {
            val date = TimeUtil.dateToTimeString(Date(), "yyyy/MM/dd")
            storePath += "$date/"
        }
        if (additionalPath != null) {
            storePath += "$additionalPath/"
        }
        val name = transferFile.name
        storePath += name

        val sysFileEntity = SysFileEntity()
        sysFileEntity.fileName = name
        sysFileEntity.originFileName = originalFileName
        sysFileEntity.storePath = storePath
        sysFileEntity.containerType = fileConfig.containerType
        sysFileEntity.moduleName = moduleName
        sysFileEntity.platformType = onflowConfig.platformType
        sysFileEntity.md5 = md5
        sysFileEntity.fileSize = transferFile.length()
        sysFileEntity.bucketName = fileConfig.bucketName
        sysFileEntity.fileGrade = fileGrade
        if (expireDate != null) {
            sysFileEntity.expireDate = TimeUtil.timeStringToDate(expireDate, TimeUtil.yyyyMMddHHmmss_HYPHEN)
        }
        // INFO: Zhouwx: 2025/9/24 用户上传
        sysFileEntity.sourceType = sourceType

        baseFileTransfer.upload(sysFileEntity, transferFile, deleteAfterUpload)
        sysFileMapper.insertEx(sysFileEntity)
        return sysFileEntity
    }

    fun transferToLocal(multipartFile: MultipartFile?, moduleName: String?): SysFileTransferToLocalDTO {
        val multipartFile = multipartFile ?: fail(ReturnCode.LACK_PARAM, "请上传文件")
        val originalFilename = multipartFile.originalFilename ?: fail(ReturnCode.LACK_PARAM, "请上传文件")
        val fileConfig = onflowConfig.file
        var localPath = fileConfig.localPath
        if (localPath.isBlank()) {
            fail(ReturnCode.SYSTEM_ERROR, "请配置文件本地存储路径")
        }
        localPath = localPath.replace("\\", "/")
        if (!localPath.endsWith("/")) {
            localPath += "/"
        }

        val moduleName = moduleName ?: fail(ReturnCode.LACK_PARAM, "请输入模块名称")
        localPath += "$moduleName/"
        if (fileConfig.datePath) {
            val date = TimeUtil.dateToTimeString(Date(), "yyyy/MM/dd")
            localPath += "$date/"
        }

        val folderFile = File(localPath)
        if (!folderFile.exists()) {
            folderFile.mkdirs()
        }
        val lastIndexOfDot = originalFilename.lastIndexOf(".")
        val fileName = originalFilename.substring(0, lastIndexOfDot) + "_" + UUID.fastUUID().toString(true) + originalFilename.substring(lastIndexOfDot)
        localPath += fileName
        val localFile = File(localPath)
        multipartFile.transferTo(localFile)

        val dto = SysFileTransferToLocalDTO()
        dto.localFile = localFile
        dto.originFileName = originalFilename
        dto.moduleName = moduleName
        return dto
    }

}